using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
using Dapper;


namespace DapperExtensions
{
    public static partial class SqlMapperExtensions
    {       
        
        public static Task<object> ExecuteScalarAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteScalarAsync(cnn, command);
        }
        
        public static Task<T> ExecuteScalarAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteScalarAsync<T>(cnn, command);
        }
        
        public static Task<IEnumerable<dynamic>> QueryAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<dynamic>> QueryAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync(cnn, command);
        }
        
        public static Task<dynamic> QueryFirstAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstAsync(cnn, command);
        }
        
        public static Task<dynamic> QueryFirstOrDefaultAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync(cnn, command);
        }
        
        public static Task<dynamic> QuerySingleAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleAsync(cnn, command);
        }
        
        public static Task<dynamic> QuerySingleOrDefaultAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync(cnn, command);
        }
        
        public static Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<T> QueryFirstAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<T> QueryFirstOrDefaultAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<T> QuerySingleAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<T> QuerySingleOrDefaultAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<dynamic> QueryFirstAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<dynamic> QueryFirstOrDefaultAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<dynamic> QuerySingleAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<dynamic> QuerySingleOrDefaultAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type type, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync(cnn, type, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<object> QueryFirstAsync(this IDbConnection cnn, Type type, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstAsync(cnn, type, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<object> QueryFirstOrDefaultAsync(this IDbConnection cnn, Type type, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync(cnn, type, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<object> QuerySingleAsync(this IDbConnection cnn, Type type, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleAsync(cnn, type, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<object> QuerySingleOrDefaultAsync(this IDbConnection cnn, Type type, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync(cnn, type, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<T>(cnn, command);
        }
        
        public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type type, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync(cnn, type, command);
        }
        
        public static Task<object> QueryFirstAsync(this IDbConnection cnn, Type type, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstAsync(cnn, type, command);
        }
        
        public static Task<T> QueryFirstAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstAsync<T>(cnn, command);
        }
        
        public static Task<object> QueryFirstOrDefaultAsync(this IDbConnection cnn, Type type, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync(cnn, type, command);
        }
        
        public static Task<T> QueryFirstOrDefaultAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryFirstOrDefaultAsync<T>(cnn, command);
        }
        
        public static Task<object> QuerySingleAsync(this IDbConnection cnn, Type type, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleAsync(cnn, type, command);
        }
        
        public static Task<T> QuerySingleAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleAsync<T>(cnn, command);
        }
        
        public static Task<object> QuerySingleOrDefaultAsync(this IDbConnection cnn, Type type, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync(cnn, type, command);
        }
        
        public static Task<T> QuerySingleOrDefaultAsync<T>(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QuerySingleOrDefaultAsync<T>(cnn, command);
        }
        
        public static Task<int> ExecuteAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.ExecuteAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<int> ExecuteAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteAsync(cnn, command);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TThird, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(cnn, ctx.CommandText, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, CommandDefinition command, Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn> map, string splitOn = "Id")
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(cnn, command, map, splitOn);
        }
        
        public static Task<IEnumerable<TReturn>> QueryAsync<TReturn>(this IDbConnection cnn, string sql, Type[] types, Func<object[], TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryAsync<TReturn>(cnn, ctx.CommandText, types, map, ctx.Parameters, transaction, buffered, splitOn, commandTimeout, commandType);
        }
        
        public static Task<Dapper.SqlMapper.GridReader> QueryMultipleAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.QueryMultipleAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<Dapper.SqlMapper.GridReader> QueryMultipleAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.QueryMultipleAsync(cnn, command);
        }
        
        public static Task<IDataReader> ExecuteReaderAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<DbDataReader> ExecuteReaderAsync(this DbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<IDataReader> ExecuteReaderAsync(this IDbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, command);
        }
        
        public static Task<DbDataReader> ExecuteReaderAsync(this DbConnection cnn, CommandDefinition command)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, command);
        }
        
        public static Task<IDataReader> ExecuteReaderAsync(this IDbConnection cnn, CommandDefinition command, CommandBehavior commandBehavior)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, command, commandBehavior);
        }
        
        public static Task<DbDataReader> ExecuteReaderAsync(this DbConnection cnn, CommandDefinition command, CommandBehavior commandBehavior)
        {
            var ctx = new DapperContext(command.CommandText, command.Parameters);
            OnExecuting(ctx);
            command = command.Clone(command.CommandText, command.Parameters); 
            return Dapper.SqlMapper.ExecuteReaderAsync(cnn, command, commandBehavior);
        }
        
        public static Task<object> ExecuteScalarAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.ExecuteScalarAsync(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
        public static Task<T> ExecuteScalarAsync<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            var ctx = new DapperContext(sql, param);
            OnExecuting(ctx);
            return Dapper.SqlMapper.ExecuteScalarAsync<T>(cnn, ctx.CommandText, ctx.Parameters, transaction, commandTimeout, commandType);
        }
        
    }
}